//
//  EBService.swift
//  ElectrickService
//
//  Created by David on 2017/6/15.
//  Copyright © 2017年 David. All rights reserved.
//

import Cocoa

@objc protocol EBServiceDelegate{
    @objc optional func showLoginDialog(username: String?, psw: String?, imgData: Data?, codeResult: String?)
    @objc optional func updateCode(imgData: Data?, codeResult: String?)
    @objc optional func loginSuccess(result: [String])
    @objc optional func loginFailes(msg: String?)
}

class EBService {
    
//    var cookie: String?
    
    var delegate: EBServiceDelegate?
    
    let savedCookieKey = "savedCookie"
    let savedUsernameKey = "savedUsername"
    let savedPasswordKey = "savedPassword"
    
    let savedDormFullNameKey = "savedDormFullName"
    let savedDormBuildNameKey = "savedDormBuildName"
    let savedDormFloorNameKey = "savedDormFloorName"
    let savedDormRoomNameKey = "savedDormRoomName"
    let savedDormBuildIDKey = "savedDormBuildID"
    let savedDormFloorIDKey = "savedDormFloorID"
    let savedDormRoomIDKey = "savedDormRoomID"
    
    let baseUrl = "https://ecard.jluzh.com/"
    let codeUrl: URL!
    let listUrl: URL!
    let loginUrl: URL!
    
    let ocrUrl: URL!
    
//    let codeLoadFailTime = 3
    
    init(){
        codeUrl = URL(string: baseUrl + "checkCode.action")!
        listUrl = URL(string: baseUrl + "utilitRoomQueryXiaoQuData.action")!
        loginUrl = URL(string: baseUrl + "login.action")!
        
        ocrUrl = URL(string: "https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic")!
    }
    
    func start(){
        localCookie()
        
//        delegate?.showLoginDialog?(username: "asdf", psw: "asdf", imgData: nil, codeResult: nil)
    }
    
    func localCookie(){
        
//        let savedCookie = UserDefaults.standard.string(forKey: savedCookieKey)
        
        
        let savedCookie = UserDefaults.standard.data(forKey: savedCookieKey)
        
        if savedCookie == nil{
            loadCode(false)
            return
        }
        
        let cookies = NSKeyedUnarchiver.unarchiveObject(with: savedCookie!)  as? [HTTPCookie]
        
        if cookies == nil{
            loadCode(false)
            return
        }
        
        HTTPCookieStorage.shared.setCookies(cookies!, for: URL(string: baseUrl)!, mainDocumentURL: nil)
        //cookieLoaded = true
        
        loadList(buildID: nil, floorID: nil) { (list) in
            if list == nil{
                DispatchQueue.main.async {
                    self.loadCode(false)
                }
                return
            }
            
            DispatchQueue.main.async {
                let dorm = self.localDorm()
                if dorm == nil{
                    self.delegate?.loginSuccess?(result: list!)
                    return
                }
            }
        }
        
    }
    
    func loadCode(_ forceShow: Bool){
        httpGet(codeUrl, saveCookie: true, finished: { (data) in
            if data != nil{
                DispatchQueue.main.async {
                    self.ocrCode(data!, finished: { (result) in
                        DispatchQueue.main.async {
                            self.perpareLogin(codeResult: result, imgData: data, forceShow: forceShow)
                        }
                        
                    })
                }
            }else{
                DispatchQueue.main.async {
                    self.perpareLogin(codeResult: nil, imgData: data, forceShow: forceShow)
                }
                
            }
            
        })
        
    }
    
    func ocrCode(_ imgData: Data, finished: @escaping (_ result: String?) -> Void){
        let base64ImgStr = imgData.base64EncodedString()
        //print(base64ImgStr)
        let postData = ["access_token": "24.175c3471dc504197136a8822b2ea84e9.2592000.1499082841.282335-9723038", "image": base64ImgStr]
        httpFormDataPost(url: ocrUrl, postData: postData) { (data) in
            if data == nil{
                finished(nil)
                return
            }
            let res = String(data: data!, encoding: .utf8)
            if res != nil{
                print(res!)
            }
            do{
                let jObj = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSDictionary
                let resAry = jObj?.object(forKey: "words_result") as? NSArray
                let resObj = resAry?.firstObject as? NSDictionary
                let code = resObj?.object(forKey: "words") as? String
                finished(code)
            }catch let ex{
                finished(nil)
                print(ex)
            }
        }
    }
    
    func perpareLogin(codeResult: String?, imgData: Data?, forceShow: Bool){
        let username = UserDefaults.standard.string(forKey: savedUsernameKey)
        
        if username == nil{
            delegate?.showLoginDialog?(username: nil, psw: nil, imgData: imgData, codeResult: codeResult)
            return
        }
        
        let pswData = UserDefaults.standard.data(forKey: savedPasswordKey)
        var psw: String?
        
        if pswData == nil{
            delegate?.showLoginDialog?(username: username, psw: nil, imgData: imgData, codeResult: codeResult)
            return
        }
        
        psw = String(data: pswData!, encoding: .utf8)
        
        if psw == nil{
            delegate?.showLoginDialog?(username: username, psw: nil, imgData: imgData, codeResult: codeResult)
            return
        }
        
        if codeResult == nil{
            delegate?.showLoginDialog?(username: username, psw: psw, imgData: imgData, codeResult: codeResult)
            return
        }
        
        if forceShow {
            delegate?.updateCode?(imgData: imgData, codeResult: codeResult)
            return
        }
        
        doLogin(username: username!, psw: psw!, code: codeResult!)
        
    }
    
    func doLogin(username: String, psw: String, code: String){
        let postBody = ["loginMode": "express", "username": username, "password": psw, "checkCode": code]
        
        httpPost(url: loginUrl, postData: postBody) { (data) in
            if data == nil{
                DispatchQueue.main.async {
                    self.delegate?.loginFailes?(msg: "网络出错")
                }
                return
            }
            let res = String(data: data!, encoding: .utf8)
            if res == nil{
                DispatchQueue.main.async {
                    self.delegate?.loginFailes?(msg: "服务器出错")
                }
                return
            }
            DispatchQueue.main.async {
                self.loadList(buildID: nil, floorID: nil, finished: { (list) in
                    if list == nil{
                        DispatchQueue.main.async {
                            self.delegate?.loginFailes?(msg: "登陆失败，请检查用户名密码验证码是否正确")
                        }
                        return
                    }
                    
                    DispatchQueue.main.async {
                        self.delegate?.loginSuccess?(result: list!)
                    }
                    UserDefaults.standard.set(username, forKey: self.savedUsernameKey)
                    UserDefaults.standard.set(psw.data(using: .utf8), forKey: self.savedPasswordKey)
                    
                })
            }
        }
    }
    
    func loadList(buildID: String?, floorID: String?, finished: @escaping (_ list: [String]?) -> Void){
        var postBody = ["dormId": "1", "dormName": "吉林大学珠海学院"]
        
        if buildID != nil{
            postBody["buildingId"] = buildID!
            
            if floorID != nil{
                postBody["floorId"] = floorID!
            }
        }
        
        
        httpPost(url: listUrl, postData: postBody) { (data) in
            if data == nil{
                finished(nil)
                return
            }
            let res = String(data: data!, encoding: .utf8)
            if res == nil{
                finished(nil)
                return
            }
            print(res!)
            
            let list = res!.components(separatedBy: "|")
            
            if list.count < 2{
                finished(nil)
                return
            }
            
            finished(list)
        }
    }
    
    func localDorm() -> Dorm? {
        
        var dormData:[String?] = []
        dormData.append(UserDefaults.standard.string(forKey: savedDormFullNameKey))
        dormData.append(UserDefaults.standard.string(forKey: savedDormBuildNameKey))
        dormData.append(UserDefaults.standard.string(forKey: savedDormFloorNameKey))
        dormData.append(UserDefaults.standard.string(forKey: savedDormRoomNameKey))
        dormData.append(UserDefaults.standard.string(forKey: savedDormBuildIDKey))
        dormData.append(UserDefaults.standard.string(forKey: savedDormFloorIDKey))
        dormData.append(UserDefaults.standard.string(forKey: savedDormRoomIDKey))
        
        for i in dormData{
            if i == nil{
                return nil
            }
        }
        
        return Dorm(fullName: dormData[0]!, buildName: dormData[1]!, floorName: dormData[2]!, roomName: dormData[3]!, buildID: dormData[4]!, floorID: dormData[5]!, roomID: dormData[6]!)
    }
    
    func httpGet(_ url: URL, saveCookie: Bool, finished: @escaping (_ data: Data?) -> Void){
        
        var resq = URLRequest(url: url)
        resq.httpMethod = "GET"
//        if cookie != nil {
//            resq.setValue(cookie!, forHTTPHeaderField: "Cookie")
//        }
        
        
        
        URLSession.shared.dataTask(with: resq) { (data, _, _) in
            if saveCookie {
                let cookies = HTTPCookieStorage.shared.cookies!
                let cookiesData = NSKeyedArchiver.archivedData(withRootObject: cookies)
                UserDefaults.standard.set(cookiesData, forKey: self.savedCookieKey)
            }
            
            finished(data)
        }.resume()
    }
    
    func httpPost(url: URL, postData: [String: String]?, finished: @escaping (_ data: Data?) -> Void){
        var resq = URLRequest(url: url)
        resq.httpMethod = "POST"
//        resq.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
        
        if postData != nil{
            var params = ""
            
            var firstKey = true
            for key in postData!.keys{
                let value = postData![key]
                if value != nil {
                    if !firstKey {
                        params += "&"
                    }
                    params += "\(key)=\(value!)"
                    firstKey = false
                }
            }
//            print(params)
//            params = params.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed) ?? params
            resq.httpBody = params.data(using: .utf8)
        }
        
        URLSession.shared.dataTask(with: resq, completionHandler: { (data, _, _) in
            finished(data)
        }).resume()
        
    }
    
    func httpFormDataPost(url: URL, postData: [String: String]?, finished: @escaping (_ data: Data?) -> Void){
        var resq = URLRequest(url: url)
        resq.httpMethod = "POST"
        
        let boundary = "EBService1234"
        
        resq.setValue("multipart/form-data; boundary=" + boundary, forHTTPHeaderField: "Content-Type")
        
        if postData != nil{
            var params = ""
            
            for key in postData!.keys{
                let value = postData![key]
                if value != nil {
                    
                    params += "--\(boundary)\r\nContent-Disposition: form-data; name=\"\(key)\"\r\n\r\n\(value!)\r\n"
                }
            }
            
            params += "--\(boundary)--"
            
            resq.httpBody = params.data(using: .utf8)
        }
        
        URLSession.shared.dataTask(with: resq, completionHandler: { (data, _, _) in
            finished(data)
        }).resume()
    }
    
    
}
